package org.cainiao.notebook.service.impl;

import lombok.RequiredArgsConstructor;
import org.cainiao.api.lark.dto.request.docs.apireference.ObtainAllBlocksOfDocumentRequest;
import org.cainiao.api.lark.dto.request.docs.space.folder.ListItemsInFolderRequest;
import org.cainiao.api.lark.dto.response.LarkDataResponse;
import org.cainiao.api.lark.dto.response.docs.docs.apireference.document.LarkBlockPage;
import org.cainiao.api.lark.dto.response.docs.space.folder.LarkFile;
import org.cainiao.api.lark.dto.response.docs.space.folder.LarkFilePage;
import org.cainiao.api.lark.dto.response.docs.space.folder.LarkFolderMeta;
import org.cainiao.api.lark.imperative.LarkApi;
import org.cainiao.common.exception.BusinessException;
import org.cainiao.notebook.dao.repository.NoteRepository;
import org.cainiao.notebook.dto.CnBlock;
import org.cainiao.notebook.dto.LarkFolderNote;
import org.cainiao.notebook.entity.Note;
import org.cainiao.notebook.service.NoteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Comparator;
import java.util.List;

import static org.cainiao.notebook.util.Util.getSubstringAfterUnderscore;

/**
 * <br />
 * <p>
 * Author: Cai Niao(wdhlzd@163.com)<br />
 */
@Service
@RequiredArgsConstructor
public class NoteServiceImpl implements NoteService {

    private static final Logger LOGGER = LoggerFactory.getLogger(NoteServiceImpl.class);

    private final LarkApi larkApi;
    private final NoteRepository noteRepository;

    @Override
    public LarkFolderNote createLarkFolderNote(String systemUserId, long parentId, String folderToken) {
        List<Note> existNotes = noteRepository
            .findByDeletedFalseAndSystemUserIdAndParentIdAndExternalId(systemUserId, parentId, folderToken);
        if (!existNotes.isEmpty()) {
            throw new BusinessException("该目录下已存在该飞书同步笔记");
        }

        LarkDataResponse<LarkFilePage> larkDataResponse = larkApi
            .docs().space().folder().listItemsInFolder(ListItemsInFolderRequest.builder()
                .folderToken(folderToken)
                .build()).getBody();
        Assert.notNull(larkDataResponse, "larkDataResponse cannot be null");
        if (larkDataResponse.getCode() != 0) {
            LOGGER.error("调用飞书接口失败，code = {}; msg = {}, logId = {}",
                larkDataResponse.getCode(), larkDataResponse.getMsg(), larkDataResponse.getError().getLogId());
            throw new BusinessException(String.format("调用飞书接口失败：%s", larkDataResponse.getMsg()));
        }
        // TODO 校验飞书响应状态，不是 0 表示没成功，应该抛出异常

        Note note = noteRepository.save(Note.builder().systemUserId(systemUserId)
            .parentId(parentId).type(Note.TypeEnum.LARK_FOLDER).externalId(folderToken)
            .createdBy(systemUserId).updatedBy(systemUserId)
            .build());

        return LarkFolderNote.fromNote(note, larkDataResponse.getData());
    }

    @Override
    public List<Note> getChildren(long id, String systemUserId) {
        return noteRepository.findByDeletedFalseAndSystemUserIdAndParentId(systemUserId, id).stream().peek(note -> {
            if (Note.TypeEnum.LARK_FOLDER.equals(note.getType())) {
                LarkDataResponse<LarkFolderMeta> larkFolderMetaLarkDataResponse = larkApi
                    .docs().space().folder().getFolderMeta(note.getExternalId()).getBody();
                Assert.notNull(larkFolderMetaLarkDataResponse, "larkFolderMetaLarkDataResponse cannot be null");
                note.setName(larkFolderMetaLarkDataResponse.getData().getName());
            }
        }).toList();
    }

    @Override
    public LarkFilePage getLarkChildren(String token) {
        LarkDataResponse<LarkFilePage> larkDataResponse = larkApi
            .docs().space().folder().listItemsInFolder(ListItemsInFolderRequest.builder()
                .folderToken(token)
                .build()).getBody();
        Assert.notNull(larkDataResponse, "larkDataResponse cannot be null");
        LarkFilePage larkFilePage = larkDataResponse.getData();
        List<LarkFile> larkFiles = larkFilePage.getFiles();
        larkFiles.sort(Comparator.comparing(LarkFile::getName));
        larkFiles.forEach(larkFile -> larkFile.setName(getSubstringAfterUnderscore(larkFile.getName())));
        return larkFilePage;
    }

    @Override
    public List<CnBlock> getLarkBlocks(String documentId) {
        LarkDataResponse<LarkBlockPage> larkDataResponse = larkApi.docs().docsApi().apiReference().document()
            .obtainAllBlocksOfDocument(documentId, ObtainAllBlocksOfDocumentRequest.builder().build()).getBody();
        Assert.notNull(larkDataResponse, "larkDataResponse cannot be null");
        return CnBlock.fromCnBlocks(larkDataResponse.getData().getItems());
    }
}
